package com.ac.scum.log.task.face.log.counsumer.stages.gamplay;

import com.ac.common.core.id.SnowflakeIdGenerator;
import com.ac.scum.log.bean.Player;
import com.ac.scum.log.bean.ServerFTPLogBunker;
import com.ac.scum.log.task.face.log.counsumer.LogConsumer;
import com.ac.scum.log.task.face.log.counsumer.stages.GameplayLogConsumer;
import com.ac.scum.log.task.mapper.log.ServerFTPLogBunkerMapper;
import com.ac.scum.log.task.utils.map.GameMapZoneUtil;
import com.ac.scum.log.task.utils.queue.FTPQueueItem;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Service
@AllArgsConstructor
public class BunkerConsumer {
    private final GameMapZoneUtil gameMapZoneUtil;
    private final SnowflakeIdGenerator snowflakeIdGenerator;
    private final ServerFTPLogBunkerMapper serverFTPLogBunkerMapper;

    public void bunkerConsumer(List<LogConsumer.GameLogLine> lines, FTPQueueItem ftpQueueItem, GameplayLogConsumer gameplayLogConsumer) {
        try {
            Pattern voltageMatchingRegex = Pattern.compile("(\\d{4}\\.\\d{2}\\.\\d{2}-\\d{2}\\.\\d{2}\\.\\d{2}): \\[LogMinigame\\] \\[AbandonedBunkerVoltageMatchingMinigame_C\\] User: (.*?) \\((\\d+), (\\d+)\\). Success: (Yes|No)\\. Elapsed time: (\\d+\\.\\d+)\\. Failed attempts: (\\d+)\\.");
            Pattern masterSwitchboardRegex = Pattern.compile("(\\d{4}\\.\\d{2}\\.\\d{2}-\\d{2}\\.\\d{2}\\.\\d{2}): \\[LogMinigame\\] \\[AbandonedBunkerMasterSwitchboardMinigame_01_C\\] User: (.+?) \\((\\d+), (\\d+)\\). Success: (Yes|No)\\. Elapsed time: (\\d+\\.\\d+). Failed attempts: (\\d+)\\.");
            Pattern slaveSwitchboardRegex = Pattern.compile("(\\d{4}\\.\\d{2}\\.\\d{2}-\\d{2}\\.\\d{2}\\.\\d{2}): \\[LogMinigame\\] \\[AbandonedBunkerSlaveSwitchboardMinigame_01_C\\] User: (.+?) \\((\\d+), (\\d+)\\). Success: (Yes|No)\\. Elapsed time: (\\d+\\.\\d+). Failed attempts: (\\d+)\\.");
            Pattern dialPadPattern = Pattern.compile("(\\d{4}\\.\\d{2}\\.\\d{2}-\\d{2}\\.\\d{2}\\.\\d{2}): \\[LogMinigame\\] \\[DialPadMinigame\\] User: ([^(]+) \\((\\d+), (\\d+)\\)\\. Location: X=(-?\\d+\\.\\d+) Y=(-?\\d+\\.\\d+) Z=(-?\\d+\\.\\d+)\\. Guessed Combination: (-?\\d+)?\\. Elapsed time since first try: (.+?)\\. Room Id: (.*?)\\. Dial Pad Location: X=(-?\\d+\\.\\d+) Y=(-?\\d+\\.\\d+) Z=(-?\\d+\\.\\d+)");
            Pattern bunkerDialPadPattern = Pattern.compile("(\\d{4}\\.\\d{2}\\.\\d{2}-\\d{2}\\.\\d{2}\\.\\d{2}): \\[LogMinigame\\] \\[AbandonedBunkerDialPadMinigame_C\\] User: (.+?) \\((\\d+), (\\d+)\\). Success: (\\w+). Elapsed time: ([\\d.]+). Failed attempts: (\\d+).");
            Pattern dialPadReTryPattern = Pattern.compile("(\\d{4}\\.\\d{2}\\.\\d{2}-\\d{2}\\.\\d{2}\\.\\d{2}): \\[LogMinigame\\] \\[DialPadMinigame\\] User: ([^(]+) \\((\\d+), (\\d+)\\)\\. Location: X=(-?\\d+\\.\\d+) Y=(-?\\d+\\.\\d+) Z=(-?\\d+\\.\\d+)\\. Guessed Combination: (-?\\d+)?\\. First try\\. Room Id: (.*?)\\. Dial Pad Location: X=(-?\\d+\\.\\d+) Y=(-?\\d+\\.\\d+) Z=(-?\\d+\\.\\d+)");

            List<ServerFTPLogBunker> bunkerList = Lists.newArrayList();

            for (LogConsumer.GameLogLine line : lines) {
                String lineContext = line.getLineContext();
                Matcher bunkerDialPadMatcher = bunkerDialPadPattern.matcher(lineContext);
                Matcher dialPadMatcher = dialPadPattern.matcher(lineContext);
                Matcher slaveSwitchboardMatcher = slaveSwitchboardRegex.matcher(lineContext);
                Matcher masterSwitchboardMatcher = masterSwitchboardRegex.matcher(lineContext);
                Matcher voltageMatchingMatcher = voltageMatchingRegex.matcher(lineContext);
                Matcher dialPadReTryMatcher = dialPadReTryPattern.matcher(lineContext);
                ServerFTPLogBunker logBunker = new ServerFTPLogBunker();
                logBunker.setType(9);
                logBunker.setId(snowflakeIdGenerator.nextId());
                logBunker.setFileId(ftpQueueItem.getFileId());
                logBunker.setServerId(ftpQueueItem.getServer().getId());
                logBunker.setLineStart(line.getStartByte());
                logBunker.setLineEnd(line.getEndByte());
                logBunker.setCreateTime(LocalDateTime.now());
                if (voltageMatchingMatcher.find()) {
                    logBunker.setType(1);
                    logBunker.setServerTime(gameplayLogConsumer.parseTimestamp(voltageMatchingMatcher.group(1), ftpQueueItem));
                    logBunker.setPlayerSteamId(Long.parseLong(voltageMatchingMatcher.group(4)));
                    Player player = gameplayLogConsumer.getOrInsertPlayerServer(logBunker.getPlayerSteamId(), logBunker.getServerId(), voltageMatchingMatcher.group(2));
                    logBunker.setPlayerId(player.getId());
                    logBunker.setSuccessFlag(voltageMatchingMatcher.group(5).trim().equalsIgnoreCase("Yes"));
                    logBunker.setElapsedTime(voltageMatchingMatcher.group(6));
                    logBunker.setFailedAttempts(Integer.parseInt(voltageMatchingMatcher.group(7)));
                } else if (masterSwitchboardMatcher.find()) {
                    extractAndPrintInformation(logBunker, masterSwitchboardMatcher, 2, ftpQueueItem, gameplayLogConsumer);
                } else if (slaveSwitchboardMatcher.find()) {
                    extractAndPrintInformation(logBunker, slaveSwitchboardMatcher, 3, ftpQueueItem, gameplayLogConsumer);
                } else if (dialPadMatcher.find()) {
                    logBunker.setType(4);
                    logBunker.setServerTime(gameplayLogConsumer.parseTimestamp(dialPadMatcher.group(1), ftpQueueItem));
                    logBunker.setPlayerSteamId(Long.parseLong(dialPadMatcher.group(4)));
                    Player player = gameplayLogConsumer.getOrInsertPlayerServer(logBunker.getPlayerSteamId(), logBunker.getServerId(), dialPadMatcher.group(2));
                    logBunker.setPlayerId(player.getId());
                    logBunker.setPlayerLocation(dialPadMatcher.group(5) + "," + dialPadMatcher.group(6) + "," + dialPadMatcher.group(7));
                    logBunker.setLocationZone(gameMapZoneUtil.getZone(Double.parseDouble(dialPadMatcher.group(5)), Double.parseDouble(dialPadMatcher.group(6))));
                    logBunker.setCombination(Integer.parseInt(dialPadMatcher.group(8) == null ? "0" : dialPadMatcher.group(8)));
                    logBunker.setElapsedTime(dialPadMatcher.group(9));
                    String roomId = dialPadMatcher.group(10);
                    logBunker.setTarget(roomId);
                    String[] roomArr = roomId.split(" ");
                    logBunker.setRoom(roomArr[0]);
                    try {
                        String[] split = roomArr[1].split("\\.");
                        logBunker.setZone(split[1].substring(split[1].lastIndexOf('_') + 1));
                        logBunker.setFloor(Integer.parseInt(split[0]));
                    } catch (Exception e) {
                        log.error("error-data: {}", lineContext);
                        log.error(e.getMessage(), e);
                    }
                    logBunker.setTargetLocation(dialPadMatcher.group(11) + "," + dialPadMatcher.group(12) + "," + dialPadMatcher.group(13));
                    logBunker.setLocationZone(gameMapZoneUtil.getZone(Double.parseDouble(dialPadMatcher.group(11)), Double.parseDouble(dialPadMatcher.group(12))));
                } else if (dialPadReTryMatcher.find()) {
                    logBunker.setType(4);
                    logBunker.setServerTime(gameplayLogConsumer.parseTimestamp(dialPadReTryMatcher.group(1), ftpQueueItem));
                    logBunker.setPlayerSteamId(Long.parseLong(dialPadReTryMatcher.group(4)));
                    Player player = gameplayLogConsumer.getOrInsertPlayerServer(logBunker.getPlayerSteamId(), logBunker.getServerId(), dialPadReTryMatcher.group(2));
                    logBunker.setPlayerId(player.getId());
                    logBunker.setPlayerLocation(dialPadReTryMatcher.group(5) + "," + dialPadReTryMatcher.group(6) + "," + dialPadReTryMatcher.group(7));
                    logBunker.setLocationZone(gameMapZoneUtil.getZone(Double.parseDouble(dialPadReTryMatcher.group(5)), Double.parseDouble(dialPadReTryMatcher.group(6))));
                    logBunker.setCombination(Integer.parseInt(dialPadReTryMatcher.group(8) == null ? "0" : dialPadReTryMatcher.group(8)));
                    String roomId = dialPadReTryMatcher.group(9);
                    logBunker.setTarget(roomId);
                    String[] roomArr = roomId.split(" ");
                    logBunker.setRoom(roomArr[0]);
                    try {
                        String[] split = roomArr[1].split("\\.");
                        logBunker.setZone(split[1].substring(split[1].lastIndexOf('_') + 1));
                        logBunker.setFloor(Integer.parseInt(split[0]));
                    } catch (Exception e) {
                        log.error("error-data: {}", lineContext);
                        log.error(e.getMessage(), e);
                    }
                    logBunker.setTargetLocation(dialPadReTryMatcher.group(10) + "," + dialPadReTryMatcher.group(11) + "," + dialPadReTryMatcher.group(12));
                    logBunker.setLocationZone(gameMapZoneUtil.getZone(Double.parseDouble(dialPadReTryMatcher.group(10)), Double.parseDouble(dialPadReTryMatcher.group(11))));
                } else if (bunkerDialPadMatcher.find()) {
                    logBunker.setType(5);
                    logBunker.setServerTime(gameplayLogConsumer.parseTimestamp(bunkerDialPadMatcher.group(1), ftpQueueItem));
                    logBunker.setPlayerSteamId(Long.parseLong(bunkerDialPadMatcher.group(4)));
                    Player player = gameplayLogConsumer.getOrInsertPlayerServer(logBunker.getPlayerSteamId(), logBunker.getServerId(), bunkerDialPadMatcher.group(2));
                    logBunker.setPlayerId(player.getId());
                    logBunker.setSuccessFlag(bunkerDialPadMatcher.group(5).trim().equalsIgnoreCase("Yes"));
                    logBunker.setElapsedTime(bunkerDialPadMatcher.group(6));
                    logBunker.setFailedAttempts(Integer.parseInt(bunkerDialPadMatcher.group(7)));
                } else {
                    gameplayLogConsumer.commitDiscardLog(ftpQueueItem, line, "bunker no match");
                    continue;
                }
                bunkerList.add(logBunker);
            }
            bunkerList.forEach(serverFTPLogBunkerMapper::insert);
        } catch (Exception e) {
            log.error("地堡日志出现异常", e);
        }
    }

    private void extractAndPrintInformation(ServerFTPLogBunker logBunker, Matcher matcher, Integer
            circuitType, FTPQueueItem ftpQueueItem, GameplayLogConsumer gameplayLogConsumer) {
        logBunker.setType(circuitType);
        logBunker.setServerTime(gameplayLogConsumer.parseTimestamp(matcher.group(1), ftpQueueItem));
        logBunker.setPlayerSteamId(Long.parseLong(matcher.group(4)));
        Player player = gameplayLogConsumer.getOrInsertPlayerServer(logBunker.getPlayerSteamId(), logBunker.getServerId(), matcher.group(2));
        logBunker.setPlayerId(player.getId());
        logBunker.setSuccessFlag(matcher.group(5).trim().equalsIgnoreCase("Yes"));
        logBunker.setElapsedTime(matcher.group(6));
        logBunker.setFailedAttempts(Integer.parseInt(matcher.group(7)));
    }

}
